package org.p2psimulator.entity.protocol.structured.chordcycles;

import java.util.List;
import org.p2psimulator.entity.Id;
import org.p2psimulator.entity.Message;
import org.p2psimulator.entity.Peer;
import org.p2psimulator.entity.filesystem.FileSystem;
import org.p2psimulator.entity.overlaynetwork.routingtable.ChordFingerTable;
import org.p2psimulator.entity.protocol.messages.MessageTypes;
import org.p2psimulator.entity.protocol.messages.chord.ChordQuery;
import org.p2psimulator.engine.Environment;

public class ChordQueryCycle extends ChordCycle {

    private Id searchedKey;

    public ChordQueryCycle(Environment env, int transId) {
        super(env, transId);
    }

    @Override
    public String runRequestCycle(Peer p) {

        StringBuilder str = new StringBuilder("  [QUERY CYCLE]   -   ");
        FileSystem fileSystem = this.env.getFileSystem();
        ChordFingerTable table = getFingerTable(p);
        searchedKey = fileSystem.getRandomFileId();
        int cnt = 0;
        for (Id closestPreceeding : table.getFingers()) {

            Double d = (Double) closestPreceeding.getValue();
            if (d.isNaN()) {
                closestPreceeding = table.getSucessor();
                d = (Double) closestPreceeding.getValue();
                if (d.isNaN()) {
                    closestPreceeding = env.getPeerBank().getRandomPeer().getId();
                }
            }
            ChordQuery query = new ChordQuery(p.getId(), closestPreceeding, this.currentTransactionId,
                    p.getBehavior().getBehaviorType());
            query.setHOP(0);
            query.setTTL(7);
            query.setKey(searchedKey);
            query.setServentId(p.getId());

            try{
                this.env.getNetwork().sendMessage(query);
            }catch(Exception e){
                System.out.println("############# ORIG: "+p.getId()+" DEST: " + query.getDestination() + " FINGERS: " + table.getFingers());
                e.printStackTrace();
            }
            cnt++;
        }
        str.append("[CHORD QUERY REQUEST - QUERY FOR KEY: " + searchedKey + " QUERIES ENVIADAS: "+cnt + " ]");
        return str.toString();
    }

    @Override
    public String runResponseCycle(Peer p) {

        StringBuilder str = new StringBuilder("");

        List<Message> queryHitList = p.getMessageStack().get(
                MessageTypes.CHORD_QUERYHIT.getName());
        int queryHits = 0;
        if (queryHitList != null) {
            queryHits = queryHitList.size();
        }
        str.append("[ CHORD QUERY RESPONSE - QUERYHITs : " + queryHits);
        return str.toString();
    }

    @Override
    public String runSecondRequestCycle(Peer p) {
        return "";
    }

    @Override
    public String runSecondResponseCycle(Peer p) {
        return "";
    }

    public Id getSearchedKey() {
        return searchedKey;
    }

    public void setSearchedKey(Id searchedKey) {
        this.searchedKey = searchedKey;
    }
}
